#include "UserInterface.h"
#include <HAPI_lib.h>
#include "Visualisation.h"
#include "WorldModel.h"
#include "AI.h"
#include "Sound.h"


CUserInterface* CUserInterface::instance=0;

CUserInterface::CUserInterface(void):timeBlendStudio(-1), blendOver(false), displayOver(false), timeBeginDisplay(-1),
								 choice(eChoicePlay), tickMenu(150), lastTick(-1), data( new HAPI_TKeyboardData())
{}

CUserInterface::~CUserInterface(void)
{
	delete data;
	data=NULL;
}

CUserInterface& CUserInterface::getInstance(void)
{
	if(CUserInterface::instance==0)
	{
		instance=new CUserInterface();
	}
	return *instance;
}

/*initialise all the variable for the UI component*/
void CUserInterface::Initialise(int indexEntityPlayer, int indexSpriteLife, int indexFrameLife,
								int indexBorderLife, int indexSMenu, int indexSD, int indexSOption)
{
	this->indexEntityPlayer=indexEntityPlayer;
	this->indexFrameLife=indexFrameLife;
	this->indexSpriteLife=indexSpriteLife;
	this->indexBorderLife=indexBorderLife;
	this->indexMenu=indexSMenu;
	this->indexOption=indexSOption;
	this->indexD=indexSD;

	timeBeginDisplayMenu=-1;
	timeBeginBlendD=1000;
	timeBlendD=3000;
	timeDisplayD=1500;

	indexFirstEnemy=0;
	indexLastEnemy=0;
}
void CUserInterface::Close(void)
{
	delete this->instance;
	instance=0;
}

/*function that display the health of the player*/
void CUserInterface::displayHealthPlayer(int positionX, int positionY,int totalHealth, int currentHealth, 
										 int widthBar, int heightBar)
{
	VIS.displayText("HP", ePolice1, positionX,positionY,true);
	VIS.displayHealth(positionX,positionY+25,totalHealth,currentHealth,widthBar, heightBar);
}

/*function that display the number of life of the player*/
void CUserInterface::displayNumberOfLife(int positionX, int positionY, int numberOfLife)
{
	VIS.displayText("LIFE", ePolice1, positionX,positionY,true);
	VIS.displayFrame(indexBorderLife,positionX+100,positionY-10,1,true);//border
	if(numberOfLife>0)
	{
		VIS.displayNumberOfLife(positionX+69, positionY,numberOfLife,this->indexSpriteLife,this->indexFrameLife);
	}
}

/*function that display the player's number of point*/
void CUserInterface::displayPoint(int positionX, int positionY)
{
	VIS.displayNumber(WMODEL.getNumberOfPoint(), ePolice1, positionX, positionY, true);
}

/*function that display all the UI. It displays the player's number of life, points and health 
and the enemies' health.*/
void CUserInterface::displayUserInterface(void)
{
	this->displayNumberOfLife(400,10,WMODEL.getNumberOfLife(this->indexEntityPlayer));
	this->displayHealthPlayer(10,VIS.getScreenHeight()-40,WMODEL.getTotalHealth(this->indexEntityPlayer),
		WMODEL.getCurrentHealth(this->indexEntityPlayer),VIS.getScreenWidth()-20,10);

	for(int i=indexFirstEnemy;i<=indexLastEnemy;i++)
	{
		if(WMODEL.getActive(i))
		{
			VIS.displayHealth(WMODEL.getCurrentPosX(i),WMODEL.getCurrentPosY(i)+10,WMODEL.getTotalHealth(i),
				WMODEL.getCurrentHealth(i),VIS.getFrameWidth(WMODEL.getSprite(i)),5);
		}
	}
	this->displayPoint(VIS.getScreenWidth()/2-100,10);

}

/*function that display the name of the studio at the beginning of the game*/
bool CUserInterface::displayStudio(int duration, int indexSprite, HAPI_TColour* color)
{
	//if it's the beginning
	if(timeBlendStudio==-1)
	{
		timeBlendStudio=duration*3/4;
		timeDisplayStudio=duration-timeBlendStudio;
	}
	//if the blending is not over
	if(!blendOver)
	{
		VIS.clearToColor(color);
		blendOver=VIS.displayFrameBlending(0,0,indexSprite,1,timeBlendStudio);
	}
	//when the blending is over we still display the picture during a certain amount of time
	if(blendOver && !displayOver)
	{
		if(timeBeginDisplay==-1)
		{
			timeBeginDisplay=HAPI->GetTime();
		}
		VIS.displayFrame(indexSprite,0,0,1,false);
		if((int)HAPI->GetTime()>timeBeginDisplay+timeDisplayStudio)
		{
			return true;
		}
	}
	return false;	
}

/*function that display the menu of the game.*/
int CUserInterface::displayMenu(void)
{
	if(timeBeginDisplayMenu==-1)
	{
		timeBeginDisplayMenu=HAPI->GetTime();
	}
	//display the background of the menu
	VIS.displayFrame(indexMenu,0,0,1,false);
	//display the blending of the D.
	if((int)HAPI->GetTime()>=timeBeginDisplayMenu+timeBeginBlendD)
	{
		if((int)HAPI->GetTime()<timeBeginDisplayMenu+timeBeginBlendD+timeBlendD)
		{
			VIS.displayFrameBlending(340,80,indexD,1,timeBlendD);
		}
		else
		{
			VIS.displayFrame(indexD,340,80,1,true);
		}
	}
	//when the blendinf of the D is over
	if((int)HAPI->GetTime()>=timeBeginDisplayMenu+timeBeginBlendD+timeBlendD+timeDisplayD)
	{
		//display of the options of the menu
		VIS.displayText("PLAY", ePolice1, 100,380,true);
		VIS.displayText("OPTION", ePolice1, 100,410,true);
		VIS.displayText("EXIT", ePolice1, 100,440,true);

		//putting the cursor in front of the choice of the player
		switch(this->choice)
		{
			default:
				choice=eChoicePlay;
				VIS.displayCharacter('I', ePolice1, 50,380,true);
				VIS.displayCharacter('I', ePolice1, 300,380,true);
				break;

			case eChoicePlay:
				VIS.displayCharacter('I', ePolice1, 50,380,true);
				VIS.displayCharacter('I', ePolice1, 300,380,true);
				break;

			case eChoiceOption:
				VIS.displayCharacter('I', ePolice1, 50,410,true);
				VIS.displayCharacter('I', ePolice1, 300,410,true);
				break;

			case eChoiceExit:
				VIS.displayCharacter('I', ePolice1, 50,440,true);
				VIS.displayCharacter('I', ePolice1, 300,440,true);
				break;
		}
		//get the input and change the state
		if((int)HAPI->GetTime()>=lastTick+tickMenu)
		{
			if(scanCode(HK_UP) && choice!=eChoicePlay) 
			{
				choice--;
				lastTick=HAPI->GetTime();
			}
			if(scanCode(HK_DOWN) && choice!=eChoiceExit) 
			{
				choice++;
				lastTick=HAPI->GetTime();
			}
			if(scanCode(HK_RETURN))
			{
				lastTick=HAPI->GetTime();
				return choice;
			}
		}
	}
	return 0;
}

/*function that display the options menu*/
int CUserInterface::displayMenuOption(void)
{
	//display the background and the text
	VIS.displayFrame(indexMenu,0,0,1,false);
	VIS.displayFrame(indexD,340,80,1,true);
	VIS.displayText("PLAY", ePolice1, 100,380,true);
	VIS.displayText("OPTION", ePolice1, 100,410,true);
	VIS.displayText("EXIT", ePolice1, 100,440,true);
	VIS.displayCharacter('I', ePolice1, 50,410,true);
	VIS.displayCharacter('I', ePolice1, 300,410,true);
		
	VIS.displayFrame(indexOption,120,90,1,true);
	VIS.displayText("OPTIONS", ePolice1,140,100,true);
	VIS.displayText("DIFFICULTY",ePolice1, 160,140,true);
	VIS.displayText("EASY",ePolice1,180,180,true);
	VIS.displayText("NORMAL",ePolice1,180,220,true);
	VIS.displayText("HARD",ePolice1,180,260,true);

	VIS.displayText("SOUND",ePolice1,160,300,true);
	VIS.displayText("ON",ePolice1,320,300,true);
	VIS.displayText("OFF",ePolice1,400,300,true);

	VIS.displayText("RETURN", ePolice1,370,350,true);
	
	//get the input and change the state
	if((int)HAPI->GetTime()>=lastTick+tickMenu)
	{
		if(scanCode(HK_LEFT))
		{
			if(choice==eChoiceOptionSoundOff)
			{
				choice=eChoiceOptionSoundOn;
				lastTick=HAPI->GetTime();
			}
		}
		if(scanCode(HK_RIGHT))
		{
			if(choice==eChoiceOptionSoundOn)
			{
				choice=eChoiceOptionSoundOff;
				lastTick=HAPI->GetTime();
			}
		}
		if(scanCode(HK_UP))
		{
			switch(choice)
			{
				case eChoiceOptionSound:
					choice=eChoiceOptionDifficulty;
					lastTick=HAPI->GetTime();
				break;

				case eChoiceOptionReturn:
					choice=eChoiceOptionSound;
					lastTick=HAPI->GetTime();
				break;

				case eChoiceOptionHard:
					choice=eChoiceOptionNormal;
					lastTick=HAPI->GetTime();
				break;

				case eChoiceOptionNormal:
					choice=eChoiceOptionEasy;
					lastTick=HAPI->GetTime();
				break;
			}
		}
		if(scanCode(HK_DOWN))
		{
			switch(choice)
			{
				case eChoiceOptionSound:
					choice=eChoiceOptionReturn;
					lastTick=HAPI->GetTime();
				break;

				case eChoiceOptionDifficulty:
				case eChoiceOption:
					choice=eChoiceOptionSound;
					lastTick=HAPI->GetTime();
				break;

				case eChoiceOptionEasy:
					choice=eChoiceOptionNormal;
					lastTick=HAPI->GetTime();
				break;

				case eChoiceOptionNormal:
					choice=eChoiceOptionHard;
					lastTick=HAPI->GetTime();
				break;
			}
		}
		if(scanCode(HK_ESCAPE))
		{
			lastTick=HAPI->GetTime();
			return 0;
		}
		if(scanCode(HK_RETURN))
		{
			switch(choice)
			{
				case eChoiceOption:
				case eChoiceOptionDifficulty:
					choice=eChoiceOptionEasy;
					lastTick=HAPI->GetTime();
				break;
				
				case eChoiceOptionSound:
					choice=eChoiceOptionSoundOn;
					lastTick=HAPI->GetTime();
				break;

				case eChoiceOptionSoundOn:
					SOUND.setEnableSound(true);
					choice=eChoiceOptionSound;
					lastTick=HAPI->GetTime();
				break;

				case eChoiceOptionSoundOff:
					SOUND.setEnableSound(false);
					choice=eChoiceOptionSound;
					lastTick=HAPI->GetTime();
				break;

				case eChoiceOptionReturn:
					lastTick=HAPI->GetTime();
					return 0;
				break;

				case eChoiceOptionEasy:
					AI.setDifficulty(eDifficultyEasy);
					choice=eChoiceOptionDifficulty;
					lastTick=HAPI->GetTime();
				break;

				case eChoiceOptionNormal:
					AI.setDifficulty(eDifficultyNormal);
					choice=eChoiceOptionDifficulty;
					lastTick=HAPI->GetTime();
				break;

				case eChoiceOptionHard:
					AI.setDifficulty(eDifficultyHard);
					choice=eChoiceOptionDifficulty;
					lastTick=HAPI->GetTime();
				break;
			}
		}
	}

	int positionCurseurX = 0;
	int positionCurseurY = 0;

	//change the position of the cursor following the state
	switch(choice)
	{
		case eChoiceOption:
		case eChoiceOptionDifficulty:
			positionCurseurX=120;
			positionCurseurY=140;
		break;

		case eChoiceOptionSound:
			positionCurseurX=120;
			positionCurseurY=300;
		break;

		case eChoiceOptionSoundOn:
			positionCurseurX=300;
			positionCurseurY=300;
		break;

		case eChoiceOptionSoundOff:
			positionCurseurX=380;
			positionCurseurY=300;
		break;

		case eChoiceOptionReturn:
			positionCurseurX=340;
			positionCurseurY=350;
		break;

		case eChoiceOptionEasy:
			positionCurseurX=160;
			positionCurseurY=180;
		break;

		case eChoiceOptionNormal:
			positionCurseurX=160;
			positionCurseurY=220;
		break;

		case eChoiceOptionHard:
			positionCurseurX=160;
			positionCurseurY=260;
		break;

	}
	//display the cursor
	VIS.displayCharacter('I',ePolice1,positionCurseurX,positionCurseurY,true);
	return choice;
}

/*function that get the input from the keyboard*/
void CUserInterface::getKeyboardData(void)
{
	HAPI->GetKeyboardData(data);
}
/*function that return false if the key keyboard has been pressed or else it returns false*/
bool CUserInterface::scanCode(int keyboard)
{
	return this->data->scanCode[keyboard];
}

void CUserInterface::setIndexFirstEnemy(int indexFirstEnemy)
{
	this->indexFirstEnemy=indexFirstEnemy;
}
void CUserInterface::setIndexLastEnemy(int indexLastEnemy)
{
	this->indexLastEnemy=indexLastEnemy;
}